﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data;

namespace Sinacor.Infra.Tools.ServiceRegistration.Data
{
    public class Attribute : ResourceAccess
    {
        #region Methods

        public List<Entity.Attribute> SelectAttribute(Entity.Attribute entity, bool addCharacterLike)
        {
            List<Entity.Attribute> response = null;

            StringBuilder sql = new StringBuilder();

            sql.AppendLine("SELECT ");
            sql.AppendLine("    ATRB.COD_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    ATRB.COD_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    ATRB.NOME_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    ATRB.DESC_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    ATRB.COD_CLAS_ATRB, ");
            sql.AppendLine("    TIPO.NOME_NAMS, ");
            sql.AppendLine("    TIPO.NOME_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    ATRB.DATA_ALTE, ");
            sql.AppendLine("    (SELECT MAX(DATA_ALTE) FROM TFWDMOD) DATA_ALTE_MAX ");
            sql.AppendLine("FROM ");
            sql.AppendLine("    TFWDATRB_TIPO_PARM_RETO_MET ATRB INNER JOIN ");
            sql.AppendLine("    TFWDTIPO_PARM_RETO_MET TIPO ON ");
            sql.AppendLine("    ATRB.COD_TIPO_PARM_RETO_MET = TIPO.COD_TIPO_PARM_RETO_MET ");
            sql.AppendLine("WHERE ");
            sql.AppendLine("    (ATRB.COD_ATRB_TIPO_PARM_RETO_MET = :COD_ATRB_TIPO_PARM_RETO_MET OR :COD_ATRB_TIPO_PARM_RETO_MET IS NULL) AND ");
            sql.AppendLine("    (ATRB.COD_TIPO_PARM_RETO_MET = :COD_TIPO_PARM_RETO_MET OR :COD_TIPO_PARM_RETO_MET IS NULL) AND ");
            sql.AppendLine("    (UPPER(ATRB.NOME_ATRB_TIPO_PARM_RETO_MET) LIKE UPPER(:NOME_ATRB_TIPO_PARM_RETO_MET) OR :NOME_ATRB_TIPO_PARM_RETO_MET IS NULL) AND ");
            sql.AppendLine("    (UPPER(ATRB.DESC_ATRB_TIPO_PARM_RETO_MET) LIKE UPPER(:DESC_ATRB_TIPO_PARM_RETO_MET) OR :DESC_ATRB_TIPO_PARM_RETO_MET IS NULL) AND ");
            sql.AppendLine("    (ATRB.COD_CLAS_ATRB = :COD_CLAS_ATRB OR :COD_CLAS_ATRB IS NULL) ");
            sql.AppendLine("ORDER BY NOME_ATRB_TIPO_PARM_RETO_MET");

            using (IDbCommand command = this.GetSqlStringCommand(sql.ToString()))
            {
                this.AddInParameter(command, "COD_ATRB_TIPO_PARM_RETO_MET", DbType.Int32, entity.AttributeId);
                this.AddInParameter(command, "COD_TIPO_PARM_RETO_MET", DbType.Int32, entity.Type != null ? entity.Type.TypeId : null);
                this.AddInParameter(command, "NOME_ATRB_TIPO_PARM_RETO_MET", DbType.String, addCharacterLike == true ? AddCharacterLike(entity.AttributeName) : entity.AttributeName);
                this.AddInParameter(command, "DESC_ATRB_TIPO_PARM_RETO_MET", DbType.String, addCharacterLike == true ? AddCharacterLike(entity.Description) : entity.Description);

                if (entity.ParentTypeId != 0)
                    this.AddInParameter(command, "COD_CLAS_ATRB", DbType.Int32, entity.ParentTypeId);
                else
                    this.AddInParameter(command, "COD_CLAS_ATRB", DbType.Int32, DBNull.Value);

                response = this.FindAll<Entity.Attribute>(command,
                    (
                        reader => new Entity.Attribute
                        {
                            AttributeId = reader.GetValue<int>("COD_ATRB_TIPO_PARM_RETO_MET"),
                            AttributeName = reader.GetValue<string>("NOME_ATRB_TIPO_PARM_RETO_MET"),
                            Description = reader.GetValue<string>("DESC_ATRB_TIPO_PARM_RETO_MET"),
                            Type = GetType(reader.GetValue<int>("COD_TIPO_PARM_RETO_MET"), reader.GetValue<string>("NOME_NAMS"), reader.GetValue<string>("NOME_TIPO_PARM_RETO_MET")),
                            ParentTypeId = reader.GetValue<int>("COD_CLAS_ATRB"),
                            DateChange = reader.GetValue<DateTime>("DATA_ALTE"),
                            IsItemDivergent = !reader.GetValue<DateTime>("DATA_ALTE").Equals(reader.GetValue<DateTime>("DATA_ALTE_MAX")),
                        }
                    )
                );
            }

            var a = from n in response
                    where n.IsItemDivergent
                    select n;

            return response;
        }

        public Entity.Attribute InsertAttribute(Entity.Attribute entity)
        {
            StringBuilder sql = new StringBuilder();

            sql.AppendLine("INSERT INTO TFWDATRB_TIPO_PARM_RETO_MET ( ");
            sql.AppendLine("    COD_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    COD_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    NOME_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    DESC_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    COD_CLAS_ATRB, ");
            sql.AppendLine("    DATA_ALTE ");
            sql.AppendLine("    ) VALUES ( ");
            sql.AppendLine("    :COD_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    :COD_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    :NOME_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    :DESC_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("    :COD_CLAS_ATRB, ");

            if (entity.DataOrigin == Entity.DataOrigin.Loader)
                sql.AppendLine("    :DATA_ALTE) ");
            else
                sql.AppendLine("    (SELECT MAX(DATA_ALTE) FROM TFWDMOD)) ");            

            using (IDbCommand command = this.GetSqlStringCommand(sql.ToString()))
            {
                this.AddInParameter(command, "COD_ATRB_TIPO_PARM_RETO_MET", DbType.Int32, entity.AttributeId);
                this.AddInParameter(command, "COD_TIPO_PARM_RETO_MET", DbType.Int32, entity.Type != null ? entity.Type.TypeId : null);
                this.AddInParameter(command, "NOME_ATRB_TIPO_PARM_RETO_MET", DbType.String, entity.AttributeName);
                this.AddInParameter(command, "DESC_ATRB_TIPO_PARM_RETO_MET", DbType.String, entity.Description);

                if (entity.DataOrigin == Entity.DataOrigin.Loader)
                    this.AddInParameter(command, "DATA_ALTE", DbType.Date, entity.DateChange);

                if (entity.ParentTypeId != 0)
                    this.AddInParameter(command, "COD_CLAS_ATRB", DbType.Int32, entity.ParentTypeId);
                else
                    this.AddInParameter(command, "COD_CLAS_ATRB", DbType.Int32, DBNull.Value);

                this.ExecuteNonQuery(command);
            }

            return entity;
        }

        public void UpdateAttribute(Entity.Attribute entity)
        {
            StringBuilder sql = new StringBuilder();

            sql.AppendLine("UPDATE TFWDATRB_TIPO_PARM_RETO_MET SET ");
            sql.AppendLine("COD_TIPO_PARM_RETO_MET = :COD_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("NOME_ATRB_TIPO_PARM_RETO_MET = :NOME_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("DESC_ATRB_TIPO_PARM_RETO_MET = :DESC_ATRB_TIPO_PARM_RETO_MET, ");
            sql.AppendLine("COD_CLAS_ATRB = :COD_CLAS_ATRB ");

            if (entity.DataOrigin == Entity.DataOrigin.Loader)
                sql.AppendLine(", DATA_ALTE = :DATA_ALTE ");

            sql.AppendLine("WHERE COD_ATRB_TIPO_PARM_RETO_MET = :COD_ATRB_TIPO_PARM_RETO_MET ");

            using (IDbCommand command = this.GetSqlStringCommand(sql.ToString()))
            {
                this.AddInParameter(command, "COD_ATRB_TIPO_PARM_RETO_MET", DbType.Int32, entity.AttributeId);
                this.AddInParameter(command, "COD_TIPO_PARM_RETO_MET", DbType.Int32, entity.Type != null ? entity.Type.TypeId : null);
                this.AddInParameter(command, "NOME_ATRB_TIPO_PARM_RETO_MET", DbType.String, entity.AttributeName);
                this.AddInParameter(command, "DESC_ATRB_TIPO_PARM_RETO_MET", DbType.String, entity.Description);
                
                if (entity.DataOrigin == Entity.DataOrigin.Loader)
                    this.AddInParameter(command, "DATA_ALTE", DbType.Date, entity.DateChange);

                if (entity.ParentTypeId != 0)
                    this.AddInParameter(command, "COD_CLAS_ATRB", DbType.Int32, entity.ParentTypeId);
                else
                    this.AddInParameter(command, "COD_CLAS_ATRB", DbType.Int32, DBNull.Value);

                this.ExecuteNonQuery(command);
            }
        }

        public void DeleteAttribute(Entity.Attribute entity)
        {
            string sql = "DELETE FROM TFWDATRB_TIPO_PARM_RETO_MET WHERE COD_ATRB_TIPO_PARM_RETO_MET = :COD_ATRB_TIPO_PARM_RETO_MET";

            using (IDbCommand command = this.GetSqlStringCommand(sql))
            {
                this.AddInParameter(command, "COD_ATRB_TIPO_PARM_RETO_MET", DbType.Int32, entity.AttributeId);
                this.ExecuteNonQuery(command);
            }
        }

        public void DeleteAttributeByParentTypeId(Entity.Attribute entity)
        {
            string sql = "DELETE FROM TFWDATRB_TIPO_PARM_RETO_MET WHERE COD_CLAS_ATRB = :COD_CLAS_ATRB";

            using (IDbCommand command = this.GetSqlStringCommand(sql))
            {
                this.AddInParameter(command, "COD_CLAS_ATRB", DbType.Int32, entity.ParentTypeId);
                this.ExecuteNonQuery(command);
            }
        }

        public int GetNextAttributeId()
        {
            int retorno = 0;
            string sql = " SELECT NVL(MAX(COD_ATRB_TIPO_PARM_RETO_MET) + 1, 1) FROM TFWDATRB_TIPO_PARM_RETO_MET ";

            using (IDbCommand command = this.GetSqlStringCommand(sql))
            {
                retorno = Convert.ToInt32(this.ExecuteScalar(command));
            }

            return retorno;
        }

        private Entity.Type GetType(int type_id, string name_space, string type_name)
        {
            //Type t = new Type();
            //List<Entity.Type> responseList = null;
            //Entity.Type response = null;

            //if (type_id != parent_type_id)
            //{
            //    if (type_id != 0)
            //    {
            //        responseList = t.SelectType(new Entity.Type { TypeId = type_id }, false);

            //        if (responseList != null && responseList.Count > 0)
            //            response = responseList[0];
            //    }
            //}
            //else
            //{
            //    response = new Entity.Type { TypeId = type_id };
            //}

            //return response;

            return new Entity.Type { TypeId = type_id, Namespace = name_space, TypeName = type_name };
        }

        #endregion
    }
}